/**
 * 
 */
package com.et114.components.acegi.vote;

import java.util.Iterator;

import org.acegisecurity.Authentication;
import org.acegisecurity.ConfigAttribute;
import org.acegisecurity.ConfigAttributeDefinition;
import org.acegisecurity.GrantedAuthority;
import org.acegisecurity.GrantedAuthorityImpl;
import org.acegisecurity.providers.dao.cache.EhCacheBasedUserCache;
import org.acegisecurity.vote.AccessDecisionVoter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.util.Assert;

import com.et114.components.acegi.Constants;

/**
 * @author guanhw
 */
public class UserVoter implements AccessDecisionVoter{
	private String					userPrefix	= Constants.VOTER_USER_PREFIX;
	private Log						logger		= LogFactory.getLog ( this.getClass ( ) );
	private EhCacheBasedUserCache	userCache;
	private boolean					withCache	= true;
	
	public UserVoter ( ) {
		// TODO Auto-generated constructor stub
	}

	public boolean supports ( ConfigAttribute attribute ) {
		// TODO Auto-generated method stub
		if ( ( attribute.getAttribute() != null )
				&& attribute.getAttribute().startsWith( getUserPrefix ( ) ) ) {
			return true;
		} else {
			return false;
		}
	}

	public boolean supports ( Class clazz ) {
		// TODO Auto-generated method stub
		 return true;
	}

	public int vote ( Authentication authentication , Object object , ConfigAttributeDefinition config ) {
		// TODO Auto-generated method stub
		logger.debug (  "进入user 用户投票器！！！"  ) ;
		int result = ACCESS_ABSTAIN;
		GrantedAuthority[] userGas = new GrantedAuthority[ 0 ] ; 
		if ( userCache == null ) {
			userGas = authentication.getAuthorities ( ) ;
			if ( userGas.length == 0  ) {
				userGas = new GrantedAuthority [ 1 ];
				userGas [ 0 ] = new GrantedAuthorityImpl (
						Constants.VOTER_USER_PREFIX );				
			}
		} else {
			if ( withCache ) {
				if ( userCache.getUserFromCache ( authentication.getName ( ) ) == null ) return ACCESS_ABSTAIN ;
				userGas = userCache.getUserFromCache ( authentication.getName ( ) ).getAuthorities ( ) ;
			}
			else {
				userGas = authentication.getAuthorities ( ) ;				
			}
			if ( userGas.length == 0  ) {
				userGas = new GrantedAuthority [ 1 ];
				userGas [ 0 ] = new GrantedAuthorityImpl (
						Constants.VOTER_USER_PREFIX );				
			}					
			/*
			if ( userCache.getUserFromCache ( authentication.getName ( ) ) == null ) {
				return ACCESS_ABSTAIN;
			} else {
				userGas = userCache.getUserFromCache (
						authentication.getName ( ) ).getAuthorities ( );
				if ( userGas .length == 0  ) {
					userGas = new GrantedAuthority [ 1 ];
					userGas [ 0 ] = new GrantedAuthorityImpl ( Constants.VOTER_USER_PREFIX );					
				}
			}*/
		}
		if ( logger.isDebugEnabled ( ) ) {
			for ( int i = 0 ; i < userGas.length ; i ++ ) {
				logger.debug ( "当前用户" + authentication.getName ( )
						+ "..............." + userGas [ i ].getAuthority ( ) );
			}
		}
		
		Iterator iter = config.getConfigAttributes();

		while ( iter.hasNext() ) {
			ConfigAttribute attribute = ( ConfigAttribute ) iter.next();

			if ( this.supports( attribute ) ) {
				result = ACCESS_DENIED;
				if ( logger.isDebugEnabled ( ) ) 
					logger.debug(  "has.." +  authentication.getName()  + " must has.. " + attribute.getAttribute()   ) ; 

				// Attempt to find a matching granted authority
				for ( int i = 0 ; i < userGas.length ; i ++ ) {
					if ( attribute.getAttribute ( ).equals (
							userGas [ i ].getAuthority ( ) ) ) {
						return ACCESS_GRANTED;
					}
				}
			}
		}
		logger.debug(  "当前用户：" +  authentication.getName()  + " 投票结果： " + result   ) ; 
		return result;
	}

	public String getUserPrefix ( ) {
		return userPrefix;
	}

	public void setUserPrefix ( String userPrefix ) {
		Assert.notNull( userPrefix, "userPrefix must not be null" );
		Constants.VOTER_USER_PREFIX = userPrefix ;
		this.userPrefix = userPrefix;
	}

	public EhCacheBasedUserCache getUserCache ( ) {
		return userCache;
	}

	public void setUserCache ( EhCacheBasedUserCache userCache ) {
		this.userCache = userCache;
	}

	public boolean getWithCache ( ) {
		return withCache;
	}

	public void setWithCache ( boolean withCache ) {
		this.withCache = withCache;
	}

}
